/**
 * hook_helpers.c - 钩子框架辅助函数库
 *
 * 提供一组便于用户在钩子中直接使用的helper函数，
 * 类似于eBPF helper函数，帮助简化常见操作。
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <sys/time.h>
#include <pthread.h>
#include <errno.h>
#include <stdarg.h>
#include <signal.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include <dirent.h>
#include <ctype.h>

#include "../../include/hook_framework.h"

/* 文件操作辅助函数 */

/**
 * 快速判断路径是否存在
 * @param path 要检查的路径
 * @return 存在返回1，不存在返回0
 */
int helper_path_exists(const char* path) {
    if (!path) return 0;
    struct stat st;
    return (stat(path, &st) == 0);
}

/**
 * 判断路径是否为目录
 * @param path 要检查的路径
 * @return 是目录返回1，否则返回0
 */
int helper_is_directory(const char* path) {
    if (!path) return 0;
    struct stat st;
    if (stat(path, &st) != 0) return 0;
    return S_ISDIR(st.st_mode);
}

/**
 * 判断路径是否为常规文件
 * @param path 要检查的路径
 * @return 是文件返回1，否则返回0
 */
int helper_is_file(const char* path) {
    if (!path) return 0;
    struct stat st;
    if (stat(path, &st) != 0) return 0;
    return S_ISREG(st.st_mode);
}

/**
 * 获取文件大小
 * @param path 文件路径
 * @return 文件大小，失败返回-1
 */
long helper_get_file_size(const char* path) {
    if (!path) return -1;
    struct stat st;
    if (stat(path, &st) != 0) return -1;
    return st.st_size;
}

/**
 * 读取文件内容
 * @param path 文件路径
 * @param buffer 输出缓冲区
 * @param size 缓冲区大小
 * @return 读取的字节数，失败返回-1
 */
ssize_t helper_read_file(const char* path, void* buffer, size_t size) {
    if (!path || !buffer || size == 0) return -1;
    
    int fd = open(path, O_RDONLY);
    if (fd == -1) return -1;
    
    ssize_t bytes_read = read(fd, buffer, size - 1);
    if (bytes_read >= 0) {
        ((char*)buffer)[bytes_read] = '\0';  // 确保字符串终止
    }
    
    close(fd);
    return bytes_read;
}

/**
 * 写入文件内容
 * @param path 文件路径
 * @param data 要写入的数据
 * @param size 数据大小
 * @return 写入的字节数，失败返回-1
 */
ssize_t helper_write_file(const char* path, const void* data, size_t size) {
    if (!path || !data) return -1;
    
    int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fd == -1) return -1;
    
    ssize_t bytes_written = write(fd, data, size);
    close(fd);
    return bytes_written;
}

/**
 * 快速判断文件是否可读
 * @param path 文件路径
 * @return 可读返回1，否则返回0
 */
int helper_is_readable(const char* path) {
    return access(path, R_OK) == 0;
}

/**
 * 快速判断文件是否可写
 * @param path 文件路径
 * @return 可写返回1，否则返回0
 */
int helper_is_writable(const char* path) {
    return access(path, W_OK) == 0;
}

/**
 * 快速判断文件是否可执行
 * @param path 文件路径
 * @return 可执行返回1，否则返回0
 */
int helper_is_executable(const char* path) {
    return access(path, X_OK) == 0;
}

/**
 * 创建目录（包括多级目录）
 * @param path 目录路径
 * @param mode 权限模式
 * @return 成功返回1，失败返回0
 */
int helper_mkdir_p(const char* path, mode_t mode) {
    if (!path) return 0;
    
    char tmp[PATH_MAX];
    char* p = NULL;
    size_t len;
    
    snprintf(tmp, sizeof(tmp), "%s", path);
    len = strlen(tmp);
    if (tmp[len - 1] == '/') {
        tmp[len - 1] = 0;
    }
    
    for (p = tmp + 1; *p; p++) {
        if (*p == '/') {
            *p = 0;
            if (mkdir(tmp, mode) != 0) {
                if (errno != EEXIST) return 0;
            }
            *p = '/';
        }
    }
    
    if (mkdir(tmp, mode) != 0) {
        if (errno != EEXIST) return 0;
    }
    
    return 1;
}

/* 字符串处理辅助函数 */

/**
 * 安全的字符串复制
 * @param dst 目标缓冲区
 * @param src 源字符串
 * @param size 目标缓冲区大小
 * @return 目标缓冲区
 */
char* helper_strncpy(char* dst, const char* src, size_t size) {
    if (!dst || !src || size == 0) return dst;
    
    size_t i;
    for (i = 0; i < size - 1 && src[i]; i++) {
        dst[i] = src[i];
    }
    dst[i] = '\0';
    
    return dst;
}

/**
 * 检查字符串是否以指定前缀开始
 * @param str 要检查的字符串
 * @param prefix 前缀
 * @return 匹配返回1，否则返回0
 */
int helper_starts_with(const char* str, const char* prefix) {
    if (!str || !prefix) return 0;
    size_t prefix_len = strlen(prefix);
    return strncmp(str, prefix, prefix_len) == 0;
}

/**
 * 检查字符串是否以指定后缀结束
 * @param str 要检查的字符串
 * @param suffix 后缀
 * @return 匹配返回1，否则返回0
 */
int helper_ends_with(const char* str, const char* suffix) {
    if (!str || !suffix) return 0;
    
    size_t str_len = strlen(str);
    size_t suffix_len = strlen(suffix);
    
    if (suffix_len > str_len) return 0;
    return strcmp(str + (str_len - suffix_len), suffix) == 0;
}

/**
 * 查找字符串中的子串
 * @param str 要检查的字符串
 * @param substr 要查找的子串
 * @return 找到返回1，否则返回0
 */
int helper_contains(const char* str, const char* substr) {
    if (!str || !substr) return 0;
    return strstr(str, substr) != NULL;
}

/**
 * 转换字符串为小写
 * @param str 要转换的字符串
 */
void helper_str_tolower(char* str) {
    if (!str) return;
    
    for (char* p = str; *p; p++) {
        *p = tolower(*p);
    }
}

/**
 * 转换字符串为大写
 * @param str 要转换的字符串
 */
void helper_str_toupper(char* str) {
    if (!str) return;
    
    for (char* p = str; *p; p++) {
        *p = toupper(*p);
    }
}

/**
 * 分割字符串
 * @param str 要分割的字符串
 * @param delim 分隔符
 * @param result 结果数组
 * @param max_tokens 最大令牌数
 * @return 分割的令牌数
 */
int helper_str_split(const char* str, const char* delim, char** result, int max_tokens) {
    if (!str || !delim || !result || max_tokens <= 0) return 0;
    
    char* saveptr;
    char* token;
    char* str_copy = strdup(str);
    int count = 0;
    
    if (!str_copy) return 0;
    
    token = strtok_r(str_copy, delim, &saveptr);
    while (token && count < max_tokens) {
        result[count++] = strdup(token);
        token = strtok_r(NULL, delim, &saveptr);
    }
    
    free(str_copy);
    return count;
}

/**
 * 释放分割的字符串数组
 * @param tokens 令牌数组
 * @param count 令牌数量
 */
void helper_free_tokens(char** tokens, int count) {
    if (!tokens) return;
    
    for (int i = 0; i < count; i++) {
        if (tokens[i]) {
            free(tokens[i]);
        }
    }
}

/* 网络辅助函数 */

/**
 * 检查地址是否是本地环回地址
 * @param addr 要检查的IP地址字符串
 * @return 是环回地址返回1，否则返回0
 */
int helper_is_loopback(const char* addr) {
    if (!addr) return 0;
    
    if (strcmp(addr, "127.0.0.1") == 0 || 
        strcmp(addr, "::1") == 0 || 
        strcmp(addr, "localhost") == 0) {
        return 1;
    }
    
    struct in_addr in_addr;
    if (inet_pton(AF_INET, addr, &in_addr)) {
        return (ntohl(in_addr.s_addr) >> 24) == 127;
    }
    
    return 0;
}

/**
 * 检查端口是否为特权端口
 * @param port 端口号
 * @return 是特权端口返回1，否则返回0
 */
int helper_is_privileged_port(int port) {
    return port > 0 && port < 1024;
}

/**
 * 获取本地主机名
 * @param buffer 输出缓冲区
 * @param size 缓冲区大小
 * @return 成功返回1，失败返回0
 */
int helper_get_hostname(char* buffer, size_t size) {
    if (!buffer || size == 0) return 0;
    return gethostname(buffer, size) == 0;
}

/* 时间辅助函数 */

/**
 * 获取可读的日期时间字符串
 * @param buffer 输出缓冲区
 * @param size 缓冲区大小
 * @param format 时间格式
 * @return 成功返回1，失败返回0
 */
int helper_get_datetime(char* buffer, size_t size, const char* format) {
    if (!buffer || size == 0) return 0;
    
    time_t now = time(NULL);
    struct tm* tm_now = localtime(&now);
    
    if (!tm_now) return 0;
    
    const char* fmt = format ? format : "%Y-%m-%d %H:%M:%S";
    return strftime(buffer, size, fmt, tm_now) > 0;
}

/**
 * 休眠指定的微秒数
 * @param usec 微秒数
 */
void helper_usleep(unsigned long usec) {
    usleep(usec);
}

/* 进程和系统辅助函数 */

/**
 * 获取当前用户名
 * @param buffer 输出缓冲区
 * @param size 缓冲区大小
 * @return 成功返回1，失败返回0
 */
int helper_get_username(char* buffer, size_t size) {
    if (!buffer || size == 0) return 0;
    
    uid_t uid = geteuid();
    struct passwd* pw = getpwuid(uid);
    
    if (!pw) return 0;
    
    helper_strncpy(buffer, pw->pw_name, size);
    return 1;
}

/**
 * 获取当前用户ID
 * @return 用户ID
 */
uid_t helper_get_uid(void) {
    return getuid();
}

/**
 * 获取有效用户ID
 * @return 有效用户ID
 */
uid_t helper_get_euid(void) {
    return geteuid();
}

/**
 * 检查当前进程是否以root权限运行
 * @return 是root返回1，否则返回0
 */
int helper_is_root(void) {
    return geteuid() == 0;
}

/**
 * 获取环境变量
 * @param name 环境变量名
 * @return 环境变量值，不存在返回NULL
 */
const char* helper_getenv(const char* name) {
    if (!name) return NULL;
    return getenv(name);
}

/**
 * 检查环境变量是否存在
 * @param name 环境变量名
 * @return 存在返回1，否则返回0
 */
int helper_has_env(const char* name) {
    return helper_getenv(name) != NULL;
}

/**
 * 获取指定PID的可执行文件路径
 * @param pid 进程ID
 * @param buffer 输出缓冲区
 * @param size 缓冲区大小
 * @return 成功返回1，失败返回0
 */
int helper_get_process_path(pid_t pid, char* buffer, size_t size) {
    if (!buffer || size == 0) return 0;
    
    char proc_path[64];
    snprintf(proc_path, sizeof(proc_path), "/proc/%d/exe", (int)pid);
    
    ssize_t len = readlink(proc_path, buffer, size - 1);
    if (len <= 0) return 0;
    
    buffer[len] = '\0';
    return 1;
}

/**
 * 获取指定PID进程的命令行
 * @param pid 进程ID
 * @param buffer 输出缓冲区
 * @param size 缓冲区大小
 * @return 成功返回1，失败返回0
 */
int helper_get_process_cmdline(pid_t pid, char* buffer, size_t size) {
    if (!buffer || size == 0) return 0;
    
    char proc_path[64];
    snprintf(proc_path, sizeof(proc_path), "/proc/%d/cmdline", (int)pid);
    
    ssize_t bytes_read = helper_read_file(proc_path, buffer, size);
    if (bytes_read <= 0) return 0;
    
    // 替换cmdline中的空字符为空格，使之可读
    for (ssize_t i = 0; i < bytes_read - 1; i++) {
        if (buffer[i] == '\0') buffer[i] = ' ';
    }
    
    return 1;
}

/**
 * 安全记录日志函数（可用在钩子内部）
 * @param file 日志文件路径
 * @param format 格式化字符串
 * @param ... 可变参数
 * @return 成功返回1，失败返回0
 */
int helper_log_to_file(const char* file, const char* format, ...) {
    if (!file || !format) return 0;
    
    int fd = open(file, O_WRONLY | O_APPEND | O_CREAT, 0644);
    if (fd < 0) return 0;
    
    char buffer[4096];
    char timestamp[64];
    
    helper_get_datetime(timestamp, sizeof(timestamp), NULL);
    int offset = snprintf(buffer, sizeof(buffer), "[%s] [PID:%d] ", timestamp, (int)getpid());
    
    va_list args;
    va_start(args, format);
    vsnprintf(buffer + offset, sizeof(buffer) - offset - 1, format, args);
    va_end(args);
    
    size_t len = strlen(buffer);
    if (buffer[len - 1] != '\n') {
        buffer[len] = '\n';
        buffer[len + 1] = '\0';
        len++;
    }
    
    write(fd, buffer, len);
    close(fd);
    return 1;
}

/* ==== 加密和哈希辅助函数 ==== */

/**
 * 一个简单的XOR加密（仅用于演示）
 */
size_t encrypt_data(const void* data, size_t size, const char* key, void* out_buffer) {
    if (!data || !key || !out_buffer || size == 0) return 0;
    
    const unsigned char* src = (const unsigned char*)data;
    unsigned char* dst = (unsigned char*)out_buffer;
    size_t key_len = strlen(key);
    
    for (size_t i = 0; i < size; i++) {
        dst[i] = src[i] ^ key[i % key_len];
    }
    
    return size;
}

/**
 * 简单的XOR解密（与encrypt_data相同）
 */
size_t decrypt_data(const void* data, size_t size, const char* key, void* out_buffer) {
    // 对于XOR加密，加密和解密是相同的操作
    return encrypt_data(data, size, key, out_buffer);
}

/**
 * 计算简单的哈希（仅用于演示）
 */
int calculate_hash(const void* data, size_t size, char* hash_buffer, size_t buffer_size) {
    if (!data || !hash_buffer || size == 0 || buffer_size < 33) return 0;
    
    const unsigned char* src = (const unsigned char*)data;
    uint32_t hash[4] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476};
    
    // 一个简单的哈希算法，仅用于演示
    for (size_t i = 0; i < size; i++) {
        hash[i % 4] = ((hash[i % 4] << 5) + hash[i % 4]) + src[i];
    }
    
    // 转换为十六进制字符串
    snprintf(hash_buffer, buffer_size, 
             "%08x%08x%08x%08x", hash[0], hash[1], hash[2], hash[3]);
    
    return 1;
} 